package mymain;

import com.sun.management.OperatingSystemMXBean;
import data.handle.Result;
import enduringLink.ClientPool;
import enduringLink.Dispatcher;
import enduringLink.MyProxy;
import enduringLink.RemoteServer;
import enduringLink.call.*;
import io.netty.channel.socket.nio.NioSocketChannel;
import local.LocalInstance;
import producer.BigFileReader;

import java.io.File;
import java.lang.management.ManagementFactory;
import java.util.LinkedList;
import java.util.Properties;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

public class Main {
    private static int fileReaderThreadNum = 7;
    public static void main(String[] args) {
        switch (args[0]){
            case "0":
                Properties properties = System.getProperties();
                System.out.println("操作系统名称：Windows 11");
//                System.out.println("操作系统的版本："+ properties.getProperty("os.version"));
                System.out.println("CPU核心数：" + Runtime.getRuntime().availableProcessors());
                OperatingSystemMXBean systemMXBean = (OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
                long totalPhysicalMemorySize = systemMXBean.getTotalPhysicalMemorySize();
                System.out.println("内存总量："+ totalPhysicalMemorySize/(1024 * 1024 * 1024) + "G");
                long freePhysicalMemorySize1 = systemMXBean.getFreePhysicalMemorySize();
                System.out.println("可用内存总量：" + freePhysicalMemorySize1/(1024 * 1024 * 1024) + "G");

                System.out.println("硬盘类型 ：SSD");
//                ProduceLink.createLink(fileReaderThreadNum);
                ClientPool clientPool = new ClientPool();
//                ExecutorService executorService = Executors.newFixedThreadPool(4);
                Scanner scanner = new Scanner(System.in);
                String next = scanner.next();
//                long beginTime = 0;
                if(next.equals("load")){
                    File file1 = new File("D:\\tcp\\tpc介绍\\part.txt");
                    File file2 = new File("D:\\tcp\\tpc介绍\\lineitem.txt");
                    BigFileReader reader = new BigFileReader(file1, file2, fileReaderThreadNum, 0, 1, 0);
                    System.out.println("开始加载......");
                    for (int i = 1; i <= 3; i++) {//给远程实例发信号，开始加载数据，开始计时

                        NioSocketChannel channel = clientPool.getClientByInstanceId(i);
                        MyProxy myProxy = new MyProxy(channel);
                        StartLoad startLoad = myProxy.proxyGet(StartLoad.class);
                        startLoad.begin();

                    }

                    reader.start();//本地正式开始加载数据
                }

                next = scanner.next();
                long selectBeginTime = 0;
                if(next.equals("select")){
                    //多线程查询 远程 + 本地
                    selectBeginTime = System.currentTimeMillis();
                    Dispatcher dis = Dispatcher.getDis();
                    MyQuantityHandle myQuantityHandle =(MyQuantityHandle) dis.get(QuantityHandle.class.getName());
                    ExecutorService executorService = Executors.newFixedThreadPool(4);
                    //开始查询，首先统计销量总和
                    executorService.execute(new Runnable() {//本地处理的销量统计
                        @Override
                        public void run() {
                            long quantitySum = LocalInstance.getQuantitySum();
                            myQuantityHandle.addQuantity(quantitySum);
                        }
                    });
                    for (int i = 1; i <= 3; i++) {//远程实例的销量统计
                        int finalI = i;
                        executorService.execute(new Runnable() {
                            @Override
                            public void run() {
                                NioSocketChannel channel = clientPool.getClientByInstanceId(finalI);
                                MyProxy myProxy = new MyProxy(channel);
                                StartSelect startSelect = myProxy.proxyGet(StartSelect.class);
                                startSelect.select();
                            }
                        });
                    }

                    long totalQuantity = 0;
                    while(true){
                        if(myQuantityHandle.isCompletion()){
//                            System.out.println("myQuantityHandle.isCompletion()");
                            totalQuantity = myQuantityHandle.getTotalQuantity();
//                            System.out.println("totalQuantity = " + totalQuantity);
                            break;
                        }
                    }

                    //向三个远程实例发送销量总和
                    for (int i = 1; i <= 3; i++) {
                        int finalI = i;
                        long finalTotalQuantity = totalQuantity;
                        executorService.execute(new Runnable() {
                            @Override
                            public void run() {
                                NioSocketChannel channel = clientPool.getClientByInstanceId(finalI);
                                MyProxy myProxy = new MyProxy(channel);
                                QuantityHandle quantityHandle = myProxy.proxyGet(QuantityHandle.class);
                                quantityHandle.setTotalQuantity(finalTotalQuantity);
                            }
                        });
                    }


                    //得到总销量和之后，进行结果查询
                    MyTransfer myTransfer = (MyTransfer) dis.get(Transfer.class.getName());


                    for (int M = 1; M <= 5; M++) {
                        for (int N = 1; N <= 5; N++) {
                            CountDownLatch downLatch = new CountDownLatch(4);
                            myTransfer.setCountDownLatch(downLatch);
                            byte brandIndex = (byte) (M * 10 + N);
                            long finalTotalQuantity1 = totalQuantity;
                            executorService.execute(new Runnable() {//本地实例结果统计
                                @Override
                                public void run() {
                                    LinkedBlockingQueue<Result> localResult = LocalInstance.getResult(brandIndex, (finalTotalQuantity1 / 2000000) * 0.3);
//                                    System.out.println("brandIndex : " + brandIndex + " results :"+localResult);
                                    myTransfer.transferData(localResult);
                                }
                            });
                            for (int i = 1; i <= 3; i++) {//远程实例结果统计
                                int finalI = i;
                                executorService.execute(new Runnable() {
                                    @Override
                                    public void run() {
                                        NioSocketChannel channel = clientPool.getClientByInstanceId(finalI);
                                        MyProxy myProxy = new MyProxy(channel);
                                        Transfer transfer = myProxy.proxyGet(Transfer.class);
                                        transfer.get(brandIndex);
                                    }
                                });
                            }
                            try {
                                downLatch.await();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            LinkedBlockingQueue<Result> results = myTransfer.getResults();
                            System.out.println("Brand#" + brandIndex + "查询结果：");
                            while(!results.isEmpty()){
                                Result result = null;
                                try {
                                    result = results.take();
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                                System.out.println("ID : " + result.getPartKey() + "  销售额 : " + String.format("%.2f", result.getTotalPrice()).toString());
                            }

                            System.out.println("==============================");
                        }
                    }
                }
                long endTime = System.currentTimeMillis();
                System.out.println("查询消耗时间 ：" + (endTime - selectBeginTime) + "ms");
                System.out.println("总执行时间 ：" + ((endTime - selectBeginTime) + LocalInstance.runningTime) + "ms");
                long freePhysicalMemorySize2 = systemMXBean.getFreePhysicalMemorySize();
                System.out.println("共消耗内存：" + (freePhysicalMemorySize1 - freePhysicalMemorySize2) / (1024 * 1024 * 1024) + "G");
                break;
            case "1":
                RemoteServer.startEnduringListen(1);
                break;
            case "2":
                RemoteServer.startEnduringListen(2);
                break;
            case "3":
                RemoteServer.startEnduringListen(3);
                break;
        }

       /* ProduceLink.createLink(fileReaderThreadNum);
        ClientPool clientPool = new ClientPool();
        Scanner scanner = new Scanner(System.in);
        String next = scanner.next();
        long beginTime = 0;
        if(next.equals("load")){
            File file1 = new File("C:\\Users\\xff\\data\\part.txt");
            File file2 = new File("C:\\Users\\xff\\data\\lineitem.txt");
            BigFileReader reader = new BigFileReader(file1, file2, fileReaderThreadNum, 0, 1, 0);
            System.out.println("开始加载......");
            for (int i = 1; i <= 3; i++) {//给远程实例发信号，将要开始加载数据，开始计时
                NioSocketChannel channel = clientPool.getClientByInstanceId(i);
                MyProxy myProxy = new MyProxy(channel);
                StartLoad startLoad = myProxy.proxyGet(StartLoad.class);
                startLoad.begin();
            }
            beginTime = System.currentTimeMillis();
            reader.start();//正式开始加载数据
        }

        next = scanner.next();
        long selectBeginTime = 0;
        if(next.equals("select")){
            //多线程查询 远程 + 本地
            selectBeginTime = System.currentTimeMillis();
            ExecutorService executorService = Executors.newFixedThreadPool(4);
            Dispatcher dis = Dispatcher.getDis();
            MyQuantityHandle myQuantityHandle =(MyQuantityHandle) dis.get(QuantityHandle.class.getName());

            //开始查询，首先统计销量总和
            executorService.execute(new Runnable() {//本地处理的销量统计
                @Override
                public void run() {
                    long quantitySum = LocalInstance.getQuantitySum();
                    myQuantityHandle.addQuantity(quantitySum);
                }
            });
            for (int i = 1; i <= 3; i++) {//远程实例的销量统计
                int finalI = i;
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        NioSocketChannel channel = clientPool.getClientByInstanceId(finalI);
                        MyProxy myProxy = new MyProxy(channel);
                        StartSelect startSelect = myProxy.proxyGet(StartSelect.class);
                        startSelect.select();
                    }
                });
            }

            long totalQuantity = 0;
            while(true){
                if(myQuantityHandle.isCompletion()){
                    totalQuantity = myQuantityHandle.getTotalQuantity();
                    break;
                }
            }

            //向三个远程实例发送销量总和
            for (int i = 1; i <= 3; i++) {
                int finalI = i;
                long finalTotalQuantity = totalQuantity;
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        NioSocketChannel channel = clientPool.getClientByInstanceId(finalI);
                        MyProxy myProxy = new MyProxy(channel);
                        QuantityHandle quantityHandle = myProxy.proxyGet(QuantityHandle.class);
                        quantityHandle.setTotalQuantity(finalTotalQuantity);
                    }
                });
            }


            //得到总销量和之后，进行结果查询
            MyTransfer myTransfer = (MyTransfer) dis.get(Transfer.class.getName());


            for (int M = 1; M <= 5; M++) {
                for (int N = 1; N < 5; N++) {
                    CountDownLatch downLatch = new CountDownLatch(4);
                    myTransfer.setCountDownLatch(downLatch);
                    byte brandIndex = (byte) (M * 10 + N);
                    long finalTotalQuantity1 = totalQuantity;
                    executorService.execute(new Runnable() {//本地实例结果统计
                        @Override
                        public void run() {
                            LinkedList<Result> localResult = LocalInstance.getResult(brandIndex, (finalTotalQuantity1 / 2000000) * 0.3);
                            myTransfer.transferData(localResult);
                        }
                    });
                    for (int i = 1; i <= 3; i++) {//远程实例结果统计
                        int finalI = i;
                        executorService.execute(new Runnable() {
                            @Override
                            public void run() {
                                NioSocketChannel channel = clientPool.getClientByInstanceId(finalI);
                                MyProxy myProxy = new MyProxy(channel);
                                Transfer transfer = myProxy.proxyGet(Transfer.class);
                                transfer.get(brandIndex);
                            }
                        });
                    }
                    try {
                        downLatch.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    LinkedList<Result> results = myTransfer.getResults();
                    System.out.println("Brand#" + brandIndex + "查询结果：");
                    for (Result result : results) {
                        System.out.println("ID : " + result.getPartKey() + "销售额 : " + result.getTotalPrice());
                    }
                    System.out.println("==============================");
                }
            }
        }
        long endTime = System.currentTimeMillis();
        System.out.println("查询消耗时间 ：" + (endTime - selectBeginTime));
        System.out.println("总执行时间 ：" + (endTime - beginTime));*/
    }
}
